#pragma once
#include <vector>
#include "rectangle.h"
#include <math.h>
#include <algorithm>
#include <iostream>
#include <map>
#include <time.h>
using namespace std;

class pos{
public:
    int x;
    int y;
    bool operator ==(const pos& p) const{
        if(p.x==this->x&&p.y==this->y){
            return true;
        }
        return false;
    }
    static double get_instance(pos point_1,pos point_2){
            return pow(pow(point_1.x-point_2.x,2)+pow(point_1.y-point_2.y,2),0.5);
    }
    pos(int x,int y){
        this->x=x;
        this->y=y;
    }

    pos(){}
};

class polygon //计算拼接用的多边形类
{
public:
    //表示法1：顶点
    vector<pos> allVertrx;
    //多边形原始顶点
    vector<pos> init_allVertrx;
    //表示法2：矩形拼接
    vector<rectangle> allRect;
    //装空白矩形（可填充）
    vector<rectangle> all_blank_Rect;
    polygon(const polygon& poly){
        this->allVertrx.assign(poly.allVertrx.begin(),poly.allVertrx.end());
        this->allRect.assign(poly.allRect.begin(),poly.allRect.end());
        this->all_blank_Rect.assign(poly.all_blank_Rect.begin(),poly.all_blank_Rect.end());
        this->init_allVertrx.assign(poly.init_allVertrx.begin(),poly.init_allVertrx.end());
    }
    polygon &operator=(const polygon& poly){
        this->allVertrx.assign(poly.allVertrx.begin(),poly.allVertrx.end());
        this->allRect.assign(poly.allRect.begin(),poly.allRect.end());
        this->all_blank_Rect.assign(poly.all_blank_Rect.begin(),poly.all_blank_Rect.end());
        this->init_allVertrx.assign(poly.init_allVertrx.begin(),poly.init_allVertrx.end());
        return *this;
    }
    bool operator ==(const polygon& p) const{
        if(p.allVertrx.size()!=this->allVertrx.size()){
            return false;
        }
        for(int i=0;i<p.allVertrx.size();i++){
            if(find(this->allVertrx.begin(),this->allVertrx.end(),p.allVertrx[i])==this->allVertrx.end()){
                return false;
            }
        }
        return true;
    }
    polygon(){}
    polygon(const vector<pos>& temp_vertrx){
        this->allVertrx.assign(temp_vertrx.begin(),temp_vertrx.end());
        this->init_allVertrx.assign(temp_vertrx.begin(),temp_vertrx.end());
    }
    pos find_nextpos( pos start, pos point,vector<pos> Vertrxs,int& state){
        for(auto iter=Vertrxs.begin();iter!=Vertrxs.end();){        //从vector中删除指定的某一个元素
            if( (*iter)==start || (*iter)==point ){
                iter=Vertrxs.erase(iter);
            }
            else{
                iter++;
            }
        }
        for(pos temp:Vertrxs){
            switch (state) {
            case -1:
                if(temp.x==point.x){
                    state=0;
                    return temp;
                }
                if(temp.y==point.y){
                    state=1;
                    return temp;
                }
                break;
            case 0:
                if(temp.y==point.y){
                    state=1;
                    return temp;
                }
                break;

            case 1:
                if(temp.x==point.x){
                    state=0;
                    return temp;
                }
                break;
            }

        }
        return pos(-1,-1);
    }

    void addVertrx(int x,int y) { this->allVertrx.push_back(pos(x,y)); }
    void toRepr2(int i=0) //将多边形转换为矩形拼接
    {
        allRect=get_rectrangles();
    }
    //获取点重复次数
    int get_occurrences(pos target,const vector<pos>& pos_vec){
        int times=0;
        for(const pos& temp:pos_vec){
            if(temp==target){
                times++;
            }
        }
        return times;
    }
    //获取空白矩形（可填充矩形）
    void get_blank_Repr(){
        this->all_blank_Rect.clear();
        vector<vector<pos>> allrect_points;
        for(rectangle rect:allRect){
            allrect_points.push_back(get_pos(rect));
        }
        vector<pos> blank_rec_points;
        for(int i=0;i<allrect_points.size();i++){
            const vector<pos>& temp_rect=allrect_points[i];
            vector<pos> other_rect;
            for(int j=0;j<allrect_points.size();j++){
                if(i==j){
                    continue;
                }
                other_rect.insert(other_rect.end(),allrect_points[j].begin(),allrect_points[j].end());
            }
            for(int i=0;i<temp_rect.size();i++){
                int times=get_occurrences(temp_rect[i],other_rect);
                if(times==1){
                    continue;
                }
                if(times==2||judge_if_online(temp_rect[i],other_rect)){
                    if(find(blank_rec_points.begin(),blank_rec_points.end(),temp_rect[i])==blank_rec_points.end())
                        blank_rec_points.push_back(temp_rect[i]);
                }
            }
        }
        vector<pos> allpoints;
        for(vector<pos> temp_rect_points:allrect_points){
            allpoints.insert(allpoints.end(),temp_rect_points.begin(),temp_rect_points.end());
        }
        const vector<pos>& four_vertices=get_pos(get_rectangle(allpoints));
        vector<pos> blank_points;
        for(pos temp:four_vertices){
            if(find(allpoints.begin(),allpoints.end(),temp)==allpoints.end()){
                blank_points.push_back(temp);
            }
        }

        if(blank_rec_points.size()==1){
            this->all_blank_Rect.push_back(get_rectangle({blank_rec_points[0],blank_points[0]}));
        }
        else{
            if(blank_points.size()==1){
                for(pos temp:blank_rec_points){
                    this->all_blank_Rect.push_back(get_rectangle({temp,blank_points[0]}));
                }
            }
            else {
                double sum_equ=pos::get_instance(blank_points[0],blank_rec_points[0])+pos::get_instance(blank_points[1],blank_rec_points[1]);
                double sum_n_equ=pos::get_instance(blank_points[0],blank_rec_points[1])+pos::get_instance(blank_points[1],blank_rec_points[0]);
                if(sum_equ<sum_n_equ){
                    this->all_blank_Rect.push_back(get_rectangle({blank_points[0],blank_rec_points[0]}));
                    this->all_blank_Rect.push_back(get_rectangle({blank_points[1],blank_rec_points[1]}));
                }
                else{
                    this->all_blank_Rect.push_back(get_rectangle({blank_points[0],blank_rec_points[1]}));
                    this->all_blank_Rect.push_back(get_rectangle({blank_points[1],blank_rec_points[0]}));
                }
            }
        }



    }

    //获取矩形的四个点
    vector<pos> get_pos(const rectangle& rect){
        return {pos(rect.x1,rect.y1),pos(rect.x2,rect.y1),pos(rect.x2,rect.y2),pos(rect.x1,rect.y2)};
    }
    bool do_judge(const pos& point,const vector<pos>& Vertrx){
        if(find(Vertrx.begin(),Vertrx.end(),point)!=Vertrx.end()){
            return true;
        }
        return judge_if_online(point,Vertrx);
    }
    //查看点是否在多边形的边上呢
    bool judge_if_online(const pos& point,const vector<pos>& Vertrx){
        int x_equ_min,x_equ_max,y_equ_min,y_equ_max;
        x_equ_min=Vertrx[0].y;
        x_equ_max=Vertrx[0].y;
        y_equ_min=Vertrx[0].x;
        y_equ_max=Vertrx[0].x;
        for(pos i:Vertrx){
            if(i.x==point.x){
                x_equ_min=i.y<x_equ_min?i.y:x_equ_min;
                x_equ_max=i.y>x_equ_max?i.y:x_equ_max;
            }
            if(i.y==point.y){
                y_equ_min=i.x<y_equ_min?i.x:y_equ_min;
                y_equ_max=i.x>y_equ_max?i.x:y_equ_max;
            }
        }
        if(x_equ_max>point.y&&x_equ_min<point.y){
            return true;
        }
        if(y_equ_max>point.x&&y_equ_min<point.x){
            return true;
        }
        return false;
    }
    bool judge_in_polygon(const pos& start,const pos& temp,const vector<pos>& Vertrx){
        pos point_1=pos(start.x,temp.y);
        pos point_2=pos(temp.x,start.y);
        return do_judge(point_1,Vertrx)&&do_judge(point_2,Vertrx);

    }

    //删除已切完的矩形
    void cut_rectangle(vector<pos>& store,const vector<pos>& points){
        for(pos point:points){
            auto iter=find(store.begin(),store.end(),point);
            if(iter==store.end()){
                store.push_back(point);
            }
            else{
                store.erase(iter);
            }
        }
    }
    vector<rectangle> get_rectrangles(){
        static int sand=0;
        int count=0;
        while (true) {
            if(count!=0){
                srand(time(0)+sand);
                random_shuffle(this->allVertrx.begin(),this->allVertrx.end());
            }
            count++;
            sand++;
            for(int i=0;i<allVertrx.size();i++){
                vector<rectangle> result;
                vector<pos> store=allVertrx;
                pos nextpos=pos();
                pos start=allVertrx[i];
                pos temp=allVertrx[i];
                while(true){
                    bool flag=false;
                    if(store.size()>4){
                        int state=-1;
                        for(int i=0;i<2;i++){
                            nextpos=find_nextpos(start,temp,store,state);
                            if(nextpos.x!=-1){
                                temp=nextpos;
                            }
                            else{
                                flag=true;
                                break;
                            }
                        }
                        if(flag==true){
                            break;
                        }
                        if(judge_in_polygon(start,temp,store)){
                            result.push_back(rectangle(min(start.x,temp.x),
                                                     min(start.y,temp.y),
                                                   max(start.x,temp.x),
                                                  max(start.y,temp.y)));
                            cut_rectangle(store,{start,temp,
                                                 pos(start.x,temp.y),
                                                 pos(temp.x,start.y)});

                            start=store[0];
                            temp=store[0];
                        }
                        else{
                            break;
                        }

                    }
                    else{
                        result.push_back(rectangle(min(min(store[0].x,store[1].x),min(store[2].x,store[3].x)),
                                min(min(store[0].y,store[1].y),min(store[2].y,store[3].y)),
                                max(max(store[0].x,store[1].x),max(store[2].x,store[3].x)),
                                max(max(store[0].y,store[1].y),max(store[2].y,store[3].y))));
                        return result;
                    }
                }

            }
        }
    }
    //移动图形位置
    static void std_pos_vec(vector<pos>& pos_vec,int std_x,int std_y)
    {
        rectangle rec_temp=get_rectangle(pos_vec);
        int x_mov=std_x-rec_temp.x1;
        int y_mov=std_y-rec_temp.y1;
        for(pos& temp:pos_vec){
            temp.x+=x_mov;
            temp.y+=y_mov;
        }
    }
    static void std_pos_vec(vector<pos>& pos_vec,int std_x,int std_y,int rec_x,int rec_y)
    {
        int x_mov=std_x-rec_x;
        int y_mov=std_y-rec_y;
        for(pos& temp:pos_vec){
            temp.x+=x_mov;
            temp.y+=y_mov;
        }
    }
    static int get_rec_area_sum(const polygon& poly){
        int area_sum=0;
        for(const rectangle& temp_rec:poly.allRect){
            area_sum+=temp_rec.area;
        }
        return area_sum;
    }
    //获取外接矩形
    static rectangle get_rectangle(const vector<pos>& points){
        int x_min,x_max,y_min,y_max;
        for(int i=0;i<points.size();i++){
            if(i==0){
                x_min=points[i].x;
                x_max=points[i].x;
                y_min=points[i].y;
                y_max=points[i].y;
            }
            else{
                x_min=points[i].x<x_min?points[i].x:x_min;
                x_max=points[i].x>x_max?points[i].x:x_max;
                y_min=points[i].y<y_min?points[i].y:y_min;
                y_max=points[i].y>y_max?points[i].y:y_max;
            }
        }
        return rectangle(x_min,y_min,x_max,y_max);
    }
};

